#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
文件相关数据模型
"""

from sqlalchemy import Column, Integer, String, BigInteger, Boolean, DateTime, ForeignKey, Index
from sqlalchemy.orm import relationship, Session
from datetime import datetime
import hashlib
from typing import List, Optional
from .base import Base, BaseRepository, QueryCondition


class VirtualFile(Base):
    """虚拟文件表 - 文件系统结构"""
    __tablename__ = 'virtual_files'
    
    id = Column(Integer, primary_key=True, autoincrement=True, comment='主键ID')
    name = Column(String(255), nullable=False, comment='文件/目录名')
    parent_id = Column(Integer, ForeignKey('virtual_files.id'), nullable=True, comment='父目录ID，NULL表示根目录')
    is_directory = Column(Boolean, nullable=False, default=False, comment='是否为目录')
    storage_file_id = Column(String(64), ForeignKey('virtual_storage.file_id'), nullable=True, comment='关联的存储文件ID（仅文件有效）')
    file_size_bytes = Column(BigInteger, nullable=False, default=0, comment='文件大小（字节）')
    media_type = Column(Integer, nullable=False, default=0, comment='媒体类型')
    large_icon_url = Column(String(500), nullable=True, comment='大缩略图URL')
    small_icon_url = Column(String(500), nullable=True, comment='小缩略图URL')
    file_extension = Column(String(20), nullable=True, comment='文件扩展名（小写，不含点）')
    created_at = Column(DateTime, nullable=False, default=datetime.utcnow, comment='创建时间')
    modified_at = Column(DateTime, nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow, comment='修改时间')
    accessed_at = Column(DateTime, comment='最后访问时间')
    deleted = Column(Boolean, nullable=False, default=False, comment='是否已删除（回收站）')
    deleted_at = Column(DateTime, nullable=True, comment='删除时间')
    original_parent_id = Column(Integer, nullable=True, comment='删除前的原始父目录ID')
    original_name = Column(String(255), nullable=True, comment='删除前的原始文件名')
    
    # 关联关系
    parent = relationship("VirtualFile", remote_side=[id], back_populates="children")
    children = relationship("VirtualFile", back_populates="parent")
    storage = relationship("VirtualStorage", back_populates="virtual_files")
    
    # 索引
    __table_args__ = (
        Index('idx_virtual_files_parent_id', 'parent_id'),
        Index('idx_virtual_files_name_parent', 'name', 'parent_id'),
        Index('idx_virtual_files_deleted', 'deleted'),
        {'comment': '虚拟文件系统表'}
    )
    
    @property
    def is_folder(self):
        """兼容性属性：is_folder指向is_directory"""
        return self.is_directory
    
    @is_folder.setter
    def is_folder(self, value):
        """兼容性属性设置器"""
        self.is_directory = value
    
    @property
    def updated_at(self):
        """兼容性属性：updated_at指向modified_at"""
        return self.modified_at
    
    @updated_at.setter
    def updated_at(self, value):
        """兼容性属性设置器"""
        self.modified_at = value
    
    @property
    def size(self):
        """获取文件大小"""
        if self.is_directory:
            return 0
        return self.file_size_bytes
    
    @property
    def mime_type(self):
        """获取MIME类型"""
        if self.is_directory:
            return 'httpd/unix-directory'
        # 根据文件扩展名推断MIME类型
        if self.file_extension:
            mime_map = {
                'txt': 'text/plain',
                'html': 'text/html',
                'css': 'text/css',
                'js': 'application/javascript',
                'json': 'application/json',
                'xml': 'application/xml',
                'pdf': 'application/pdf',
                'jpg': 'image/jpeg',
                'jpeg': 'image/jpeg',
                'png': 'image/png',
                'gif': 'image/gif',
                'svg': 'image/svg+xml',
                'mp4': 'video/mp4',
                'avi': 'video/x-msvideo',
                'mov': 'video/quicktime',
                'mp3': 'audio/mpeg',
                'wav': 'audio/wav',
                'zip': 'application/zip',
                'rar': 'application/x-rar-compressed',
                'doc': 'application/msword',
                'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'xls': 'application/vnd.ms-excel',
                'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'ppt': 'application/vnd.ms-powerpoint',
                'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
            }
            return mime_map.get(self.file_extension, 'application/octet-stream')
        return 'application/octet-stream'
    
    def get_etag(self):
        """生成ETag"""
        if self.is_directory:
            # 目录的ETag基于修改时间
            return f'"{hashlib.md5(str(self.modified_at.timestamp()).encode()).hexdigest()}"'
        else:
            # 文件的ETag基于文件ID和修改时间
            if self.storage:
                content = f"{self.storage.file_id}-{self.modified_at.timestamp()}"
                return f'"{hashlib.md5(content.encode()).hexdigest()}"'
            else:
                return f'"{hashlib.md5(str(self.modified_at.timestamp()).encode()).hexdigest()}"'


class VirtualFileRepository(BaseRepository):
    """虚拟文件Repository"""
    
    def __init__(self):
        super().__init__(VirtualFile)
    
    def find_by_name_and_parent(self, name: str, parent_id: Optional[int]) -> Optional['VirtualFile']:
        """根据名称和父目录ID查找文件或目录"""
        condition = QueryCondition()
        condition.eq(VirtualFile.name, name)
        condition.eq(VirtualFile.parent_id, parent_id)
        condition.eq(VirtualFile.deleted, False)  # 只查找未删除的文件
        return self.get_one(condition)
    
    def find_children(self, parent_id: Optional[int] = None) -> List[VirtualFile]:
        """查找子文件/目录"""
        condition = QueryCondition()
        condition.eq(VirtualFile.parent_id, parent_id)
        return self.list_by_condition(condition, order_by='name')
    
    def find_by_owner(self) -> List[VirtualFile]:
        """查找所有文件"""
        condition = QueryCondition()
        return self.list_by_condition(condition, order_by='created_at', desc_order=True)
    
    def find_directories(self, parent_id: Optional[int] = None) -> List[VirtualFile]:
        """查找目录"""
        condition = QueryCondition()
        condition.eq(VirtualFile.parent_id, parent_id)
        condition.eq(VirtualFile.is_directory, True)
        return self.list_by_condition(condition, order_by='name')
    
    def find_files(self, parent_id: Optional[int] = None) -> List[VirtualFile]:
        """查找文件（非目录）"""
        condition = QueryCondition()
        condition.eq(VirtualFile.parent_id, parent_id)
        condition.eq(VirtualFile.is_directory, False)
        return self.list_by_condition(condition, order_by='name')
    
    def find_by_storage_file_id(self, storage_file_id: str) -> List[VirtualFile]:
        """根据存储文件ID查找虚拟文件"""
        condition = QueryCondition()
        condition.eq(VirtualFile.storage_file_id, storage_file_id)
        return self.list_by_condition(condition)
    
    def find_by_path(self, path: str) -> Optional['VirtualFile']:
        """根据路径查找文件或目录"""
        if path == '/':
            return None
        
        path = path.strip('/')
        parts = path.split('/')
        
        current_parent_id = None
        
        for part in parts:
            vf = self.find_by_name_and_parent(part, current_parent_id)
            if vf is None:
                return None
            current_parent_id = vf.id
        
        return vf
    
    def create_directory(self, name: str, parent_id: Optional[int] = None) -> VirtualFile:
        """创建目录"""
        directory = VirtualFile(
            name=name,
            parent_id=parent_id,
            is_directory=True
        )
        return self.save(directory)
    
    def create_file(self, name: str, parent_id: Optional[int] = None,
                   file_size_bytes: int = 0, media_type: int = 0, 
                   large_icon_url: Optional[str] = None, small_icon_url: Optional[str] = None,
                   file_extension: Optional[str] = None, storage_file_id: Optional[str] = None) -> VirtualFile:
        """创建文件"""
        # 如果没有提供文件扩展名，从文件名中提取
        if not file_extension and '.' in name:
            file_extension = name.split('.')[-1].lower()
        
        file_obj = VirtualFile(
            name=name,
            parent_id=parent_id,
            is_directory=False,
            storage_file_id=storage_file_id,
            file_size_bytes=file_size_bytes,
            media_type=media_type,
            large_icon_url=large_icon_url,
            small_icon_url=small_icon_url,
            file_extension=file_extension
        )
        return self.save(file_obj)
    
    def move_file(self, file_id: int, new_parent_id: Optional[int], new_name: Optional[str] = None) -> bool:
        """移动文件"""
        updates = {'parent_id': new_parent_id}
        if new_name:
            updates['name'] = new_name
        return self.update_by_id(file_id, **updates)
    
    def delete_with_children(self, file_id: int) -> int:
        """删除文件及其所有子文件"""
        file = self.get_by_id(file_id)
        if not file:
            return 0
        
        deleted_count = 0
        
        if file.is_directory:
            # 递归删除子文件
            children = self.find_children(file_id)
            for child in children:
                deleted_count += self.delete_with_children(child.id)
        
        # 删除自身
        if self.delete_by_id(file_id):
            deleted_count += 1
        
        return deleted_count